<?php
/***************************************************************
*  Copyright notice
*  (c) 2009, jianyuzhu@gmail.com
*  All rights reserved
*  This script is part of the PPEMI project.
***************************************************************/

class LibXML {
	var $parser = NULL;
	var $pointer = NULL;
	var $depth = 0;
	var $parsed = false;
	
	var $xml = '';
	var $data = array();
	
	//constructor
	function LibXML() {
		
	}
	
	//setter/getter
	function setXML() {
		$this->xml = $xml;
	}
	
	function getXML() {
		return $this->xml;
	}
	
	function getData() {
		if( $this->parsed == false ) {
			$this->parse();
		}
		return $this->data;
	}
	
	//xml
	function readFromURL($url) {
		return file_get_contents($url);
	}
	
	function readFile($filename) {
		$xml = file_get_contents($filename);
		
		$this->xml = $xml;
	}
	
	function f($filename) {
		$fp = fopen($filename, 'r');
		$xml = fread($fp, filesize($filename));
		fclose($fp);
		
		$this->xml = $xml;
	}
	
	//parse
	function parse($xml = '') {
		if( $xml != '' ) {
			$this->xml = $xml;
		}
		$this->parseXML();
	}
	
	function parseXML() {
		$this->_xml_parse_init();
		$this->_xml_parse();
	}
	
	//private
	function _xml_parse_init() {
		$this->pointer = & $this->data;
		$this->parser = xml_parser_create();
		
		xml_set_object($this->parser, $this);
		xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
		xml_set_element_handler($this->parser, "_start_element_handler", "_end_element_handler");
		xml_set_character_data_handler($this->parser, "_character_data_handler");
		xml_set_processing_instruction_handler($this->parser, "_pi_handler");
		xml_set_default_handler($this->parser, "_default_handler");
	}
	
	function _xml_parse() {
		xml_parse($this->parser, $this->xml);
		xml_parser_free($this->parser);
		$this->parsed = true;
	}
	
	function _start_element_handler($parser, $name, $attributes) {
		$idx = $this->_convert_to_array($name, '@attributes');
		$idx = $this->_convert_to_array($name, 'cdata');
		if( isset($idx) ) {
			$this->pointer[$name][$idx] = array('@idx' => $idx, '@parent' => & $this->pointer);
			$this->pointer = & $this->pointer[$name][$idx];
		} else {
			$this->pointer[$name] = array('@parent' => & $this->pointer);
			$this->pointer = & $this->pointer[$name];
		}
		if( !empty($attributes) ) {
			$this->pointer['@attributes'] = $attributes;
		}
	}
	
	function _end_element_handler($parser, $name) {
		$current = & $this->pointer;
		if( isset($this->pointer['@idx']) ) {
			unset($current['@idx']);
		}
		$this->pointer = & $this->pointer['@parent'];
		unset($current['@parent']);
		if( isset($current['cdata']) && count($current) == 1 ) {
			$current = $current['cdata'];
		} elseif( empty($current['cdata']) ) {
			unset($current['cdata']);
		}
	}
	
	function _character_data_handler($parser, $data) {
		$this->pointer['cdata'] = trim($data);
	}
	
	function _pi_handler($parser, $target, $data) {
		
	}
	
	function _default_handler($parser, $data) {
		
	}
	
	//Converts a single element item into array(element[0]) if a second element of the same name is encountered.
	function _convert_to_array($name, $item) {
		if( isset($this->pointer[$name][$item]) ) {
			$content = $this->pointer[$name];
			$this->pointer[$name] = array((0) => $content);
			$idx = 1;
		} elseif( isset($this->pointer[$name]) ) {
			$idx = count($this->pointer[$name]);
			if( !isset($this->pointer[$name][0]) ) {
				foreach($this->pointer[$name] as $key => $value) {
					unset($this->pointer[$name][$key]);
					$this->pointer[$name][0][$key] = $value;
				}
			}
		} else {
			$idx = NULL;
		}
		
		return $idx;
	}
}
//
?>